import { useCallback, useEffect, useRef, useState } from 'react';
import { toCanvas } from 'html-to-image';

import { fileImageToCanvas } from '@/utils/converter';

const useCaptureReport = ({
  onCaptureReport,
  onSubmitReport,
  onCancel,
}: {
  onCaptureReport?: (e: any) => void;
  onSubmitReport: (e: any) => void;
  onCancel?: () => void;
}) => {
  const [startCapture, setStartCapture] = useState(false);
  const [showGuide, setShowGuide] = useState(false);
  const labelArray = useRef<any[]>([]);
  const hoverElemRef = useRef<any>();
  const guideElemRef = useRef<any>();

  useEffect(() => {
    prepareHoverElement();

    return () => {
      hoverElemRef.current.remove();
      hoverElemRef.current = undefined;
    };
  }, []);

  const onTriggerStart = (e: any) => {
    setShowGuide(true);
  };

  useEffect(() => {
    if (showGuide) {
      if (guideElemRef.current) return;
      const guideElement = document.createElement('div');
      guideElement.className =
        'guide-mask fixed top-0 w-full h-full bg-black/50 z-[999999]';

      const guideDialog = document.createElement('div');
      guideDialog.className =
        'absolute bottom-0 end-0 m-10 p-5 w-1/4 bg-white rounded';
      guideDialog.innerHTML = `<div>
        <div class='font-bold text-gray-800 mb-2'>反馈提交</div>
        <div class='text-sm text-gray-500'>
          您可以 <strong class='text-gray-600'>直接上传</strong> 已有的截图或在页面上 <strong class='text-gray-600'>点选区域</strong> 并进行截图
        </div>
      </div>`;
      guideDialog.insertAdjacentHTML(
        'beforeend',
        `<div class='mt-10'>
          <span class='text-sm rounded p-1 px-2 bg-gray-200 text-gray-800'>点选区域说明</span>
          <ul class='list-decimal list-inside p-0 text-gray-500 text-sm'>
            <li>鼠标移动到页面元素上方单击可 选中/反选 页面元素。</li>
            <li>当选择结束后，键盘敲击 回车 可以进行截图。</li>
          </ul>
        </div>`
      );
      const guideButton = document.createElement('div');
      guideButton.className = 'flex justify-end';
      const uploadButton = document.createElement('button');
      uploadButton.className =
        'border-none rounded bg-pink-500 text-white px-4 p-2 cursor-pointer ms-2';
      uploadButton.innerText = '直接上传';
      const selectButton = document.createElement('button');
      selectButton.className =
        'border-none rounded bg-sky-500 text-white px-4 p-2 cursor-pointer ms-2';
      selectButton.innerText = '点选区域';

      uploadButton.addEventListener(
        'click',
        (e) => {
          uploadfile();
        },
        false
      );
      selectButton.addEventListener(
        'click',
        (e) => {
          setShowGuide(false);
          setStartCapture(true);
        },
        false
      );
      guideDialog.addEventListener('click', (e) => e.stopPropagation(), false);
      guideElement.addEventListener('click', () => setShowGuide(false), false);

      guideButton.append(uploadButton, selectButton);
      guideDialog.append(guideButton);
      guideElement.append(guideDialog);
      document.body.append(guideElement);

      guideElemRef.current = guideElement;
    } else {
      if (!guideElemRef.current) return;
      guideElemRef.current.remove();
      guideElemRef.current = undefined;
    }
  }, [showGuide]);

  const uploadfile = () => {
    const fileuploader = document.createElement('input');
    fileuploader.className = 'hidden';
    fileuploader.type = 'file';
    fileuploader.accept = 'image/*';
    fileuploader.addEventListener(
      'change',
      async (e: any) => {
        const canvas = await fileImageToCanvas(e.target.files[0]);
        setShowGuide(false);
        prepareToSubmitReport(canvas);
      },
      false
    );

    fileuploader.click();
  };

  useEffect(() => {
    if (startCapture) {
      document.addEventListener('mouseover', elementHoverFunction, false);
      document.addEventListener('keydown', triggerCaptureEvent, false);

      document
        .querySelector('#root')!
        .addEventListener('click', preventClickFunction, true);
    } else {
      document.removeEventListener('mouseover', elementHoverFunction, false);
      document.removeEventListener('keydown', triggerCaptureEvent, false);
      document
        .querySelector('#root')!
        .removeEventListener('click', preventClickFunction, true);

      hoverElemRef.current.style.top = '';
      hoverElemRef.current.style.left = '';
      hoverElemRef.current.style.width = '';
      hoverElemRef.current.style.height = '';

      document
        .querySelectorAll('.hover-mask.labelled')
        .forEach((item) => item.remove());
      labelArray.current = [];
    }
  }, [startCapture]);

  const captureToCanvas = () => {
    //   width: document.body.clientWidth,
    //   height: document.body.clientHeight,
    toCanvas(document.body, {
      filter: (node) => {
        return !(
          node.classList?.contains('hover-mask') &&
          !node.classList?.contains('labelled')
        );
      },
    }).then(function (canvas) {
      setStartCapture(false);
      prepareToSubmitReport(canvas);
    });
  };

  const prepareToSubmitReport = (canvas: HTMLCanvasElement) => {
    const ctx = canvas.getContext('2d');
    // console.log(ctx);

    const { offsetHeight, clientHeight, height, width } = canvas;
    const ratio = width / height;
    const _height = document.body.clientHeight * 0.6;
    const _width = ratio * _height;

    const submitMask = document.createElement('div');
    submitMask.className =
      'submit-mask fixed top-0 w-full h-full bg-black/50 z-[999999] flex justify-center';

    const canvasContainer = document.createElement('div');
    canvasContainer.className = 'w-3/5 h-3/5 flex justify-center';
    canvas.style.height = _height + 'px';
    canvas.style.width = _width + 'px';

    const reportDesc = document.createElement('div');
    reportDesc.className =
      'absolute top-[60%] start-[20%] w-3/5 mt-4 rounded overflow-hidden';
    reportDesc.innerHTML = `<div class='absolute inset-0 flex'>
      <div class='flex-1 bg-white rounded-br'></div>
      <div class='basis-[200px] flex flex-col'>
        <div class='flex-1 bg-white rounded-br'></div>
        <div class='basis-[44px]'></div>
      </div>
    </div>`;

    const reportInput = document.createElement('textarea');
    reportInput.rows = 7;
    reportInput.placeholder = '请在此处描述您的反馈内容';
    reportInput.className =
      'report-desc relative z-10 w-full rounded focus:outline-0 border-none resize-none box-border p-2 bg-transparent';

    const reportContainer = document.createElement('div');
    reportContainer.className =
      'absolute bottom-0 end-0 ps-2 pt-2 w-[200px] h-[44px] box-border flex gap-x-2 z-10';
    const quitButton = document.createElement('button');
    quitButton.className =
      'border-none rounded bg-gray-800 text-white flex-1 cursor-pointer';
    quitButton.innerText = '放弃';
    const submitButton = document.createElement('button');
    submitButton.className =
      'border-none rounded bg-sky-500 text-white flex-1 cursor-pointer';
    submitButton.innerText = '提交';

    quitButton.addEventListener(
      'click',
      () => {
        submitMask.remove();
        onCancel && onCancel();
      },
      false
    );
    submitButton.addEventListener(
      'click',
      () => {
        const text = document.querySelector(
          '.submit-mask .report-desc'
        ) as HTMLTextAreaElement;

        if (text) {
          onSubmitReport({
            image: canvas,
            desc: text.value,
          });

          submitMask.remove();
        }
      },
      false
    );

    reportContainer.append(quitButton, submitButton);
    reportDesc.append(reportInput, reportContainer);
    submitMask.append(reportDesc);
    canvasContainer.append(canvas);
    submitMask.append(canvasContainer);
    document.body.prepend(submitMask);
  };

  const preventClickFunction = useCallback((e: any) => {
    e.preventDefault();
    e.stopPropagation();

    cloneLabelMask();

    onCaptureReport && onCaptureReport(e);
    return false;
  }, []);

  const cloneLabelMask = () => {
    const labelmask = hoverElemRef.current.cloneNode(false);
    labelmask.id = `label-${labelArray.current.length + 1}`;
    labelmask.classList.add('labelled');
    labelmask.style.pointerEvents = 'auto';
    labelmask.addEventListener('click', removeLabelMask, true);
    const maskno = document.createElement('div');
    maskno.innerText = `${labelArray.current.length + 1}`;
    maskno.style.position = 'absolute';
    maskno.style.right = '0';
    maskno.style.top = '-12px';
    maskno.style.width = '24px';
    maskno.style.height = '24px';
    maskno.style.lineHeight = '24px';
    maskno.style.textAlign = 'center';
    maskno.style.color = '#fff';
    maskno.style.borderRadius = '4px';
    maskno.style.background = 'rgba(255, 172, 24, .8)';
    maskno.style.pointerEvents = 'none';
    labelmask.append(maskno);
    document.body.prepend(labelmask);

    labelArray.current = [...labelArray.current, labelmask.id];
  };

  const triggerCaptureEvent = useCallback((e: any) => {
    if (e.key == 'Enter' && e.keyCode == 13) {
      captureToCanvas();
    }
    if (e.key == 'Escape' && e.keyCode == 27) {
      setStartCapture(false);
      onCancel && onCancel();
    }
  }, []);

  const removeLabelMask = useCallback(
    (e: any) => {
      e.target.remove();
      labelArray.current = labelArray.current.filter((l) => l !== e.target.id);
    },
    [labelArray]
  );

  const elementHoverFunction = useCallback((e: any) => {
    const coverElement: any = e.target;

    if (
      coverElement &&
      coverElement.className &&
      coverElement.nodeName.toLowerCase() !== 'path'
    ) {
      const { top, left, width, height } = coverElement.getBoundingClientRect();

      hoverElemRef.current.style.top = top + 'px';
      hoverElemRef.current.style.left = left + 'px';
      hoverElemRef.current.style.width = width + 'px';
      hoverElemRef.current.style.height = height + 'px';
    }
  }, []);

  const prepareHoverElement = () => {
    if (!hoverElemRef.current) {
      var displayElement = document.createElement('div');
      displayElement.classList.add('hover-mask');
      displayElement.style.transition =
        'top .15s, left .15s, width .3s, height .3s';
      displayElement.style.position = 'fixed';
      displayElement.style.borderRadius = '4px';
      displayElement.style.backgroundColor = 'rgba(255, 172, 24, .2)';
      displayElement.style.zIndex = '999999';
      displayElement.style.pointerEvents = 'none';

      document.body.append(displayElement);
      hoverElemRef.current = displayElement;
    }
  };

  return {
    onClick: onTriggerStart,
  };
};

export default useCaptureReport;
